import tensorflow as tf
import numpy as np
from sklearn.preprocessing import StandardScaler

# 1.	以上给予的的背景小知识的了解，请使用TensorFlow完成以下相关的题目要求。
# (1)	以下为一个判断逻异或的的数据，按照要求去做逻辑回归运算；
# ①	正确加载下图给予的亦或初始化数据（7分）
x_data = [[1, 2],
          [2, 3],
          [3, 1],
          [4, 3],
          [5, 3],
          [6, 2]]
y_data = [[0],
          [0],
          [0],
          [1],
          [1],
          [1]]
x_data = np.array(x_data, dtype=np.float)
y_data = np.array(y_data, dtype=np.float)
m, n = x_data.shape
print(x_data.shape)
print(y_data.shape)
#
# ②	合理的运用tf.placeholder进行定义（7分）
ph_x = tf.compat.v1.placeholder(tf.float32, [None, n], name='placeholder_x')
ph_y = tf.compat.v1.placeholder(tf.float32, [None, 1], name='placeholder_y')

# ③	合理的根据以上数据进行偏执和权重的设置，注意维度问题。（7分）
w = tf.Variable(tf.random.normal([2, 1]), dtype=tf.float32, name='w')
b = tf.Variable(tf.random.normal([1]), dtype=tf.float32, name='b')

# ④	调用tf.sigmoid模块完成预测模型（7分）
h = tf.sigmoid(tf.matmul(ph_x, w) + b, name='h')

# ⑤	用底层写出损失函数，注意是交叉熵分类。（7分）
cost = tf.math.negative(
    tf.reduce_mean(
        ph_y * tf.math.log(h) + (1 - ph_y) * tf.math.log(1 - h)
    ),
    name='cost'
)

# ⑥	定义梯度下降（可以选择优化器种类也行）（7分）
train = tf.compat.v1.train.GradientDescentOptimizer(learning_rate=0.01).minimize(cost)

# accuracy
acc = tf.reduce_mean(tf.cast(
    tf.equal(h > 0.5, ph_y > 0.5),
    tf.float32
), name='acc')

# ⑦	创建会话，进行运算计算图分析。（7分）
with tf.compat.v1.Session() as sess:
    with tf.compat.v1.summary.FileWriter('./log/logi_regr', sess.graph) as fw:
        pass
    sess.run(tf.compat.v1.global_variables_initializer())

    # ⑧	进行迭代运算，要求1000次
    iters = 1000
    for i in range(iters):
        wv, bv, cost_v, _, acc_v = sess.run([w, b, cost, train, acc], feed_dict={ph_x: x_data, ph_y: y_data})
        # ⑨	合理的步数（可以是40步）给出损失值结果。（7分）
        if i % 40 == 0:
            print(f'#{i + 1} cost = {cost_v} accuracy = {acc_v}')

    # ⑩	最后进入验证预测功能，要求加入正确的的注释（7分）
    x_test = [[1, 2],
              [3, 4],
              [5, 6],
              [10, 10]]
    h_test = sess.run(h, feed_dict={ph_x: x_test})  # Value of hypothesis
    print(np.c_[h_test, h_test > 0.5])  # Classes result
